 var ideon = function($){
	bluehat = ideon.bluehat || {};
	bluehat.model = bluehat.model || {};
	bluehat.collection = bluehat.collection || {};
	bluehat.view = bluehat.view || {};
	bluehat.router = bluehat.router || {};
	
	// MODELS
	bluehat.model.Focus = Backbone.Model.extend({
		defaults: {
			title:					"",
			description:			"",
		},
		
		initialize: function() {
			this.informations = new bluehat.collection.InformationCollection();
			this.informations.url = "/bluehat/focus/list/" + this.get("id") + "/information";
		},
	
		urlRoot: "http://localhost:9000/bluehat/focus/list",
		//url: "http://localhost:9000/bluehat/focus/list", 
	});
	
	bluehat.model.Information = Backbone.Model.extend({
		initialize: function() {
			this.units = new bluehat.collection.InfoUnits();
			this.units.url = "/bluehat/information/list/" + this.get("id") + "/units"
		}
	});
	
	bluehat.model.InfoUnit = Backbone.Model.extend({});
	
	bluehat.model.User = Backbone.Model.extend({
		url: function() {
			return "/bluehat/user/summary/" + this.get("id");
		},
		
		defaults: {
			firstName:			"",
			lastName:			"",
			email:				"",
		},
		
		initialize: function(options) {
			this.units = new bluehat.collection.InfoUnits();
			this.units.url = "/bluehat/user/summary/infounits/" + this.get("id");
		},
	});
	
	// COLLECTIONS
	
	// Object pageInfo for pagination.
	Backbone.Collection.prototype.pageInfo = function() {

		var info = {
		  total: this.total,
		  page: this.page,
		  perPage: this.perPage,
		  pages: Math.ceil(this.total / this.perPage),
		  prev: false,
		  next: false
		};

		var max = Math.min(this.total, this.page * this.perPage);

		if (this.total == this.pages * this.perPage) {
		  max = this.total;
		}

		info.range = [];

		for(var i = 1 ; i <= info.pages; i++) {
			info.range.push(i);
		}

		if (this.page > 1) {
		  info.prev = this.page - 1;
		}

		if (this.page < info.pages) {
		  info.next = this.page + 1;
		}

		console.log("Total: " + info.total);
		console.log("Page: " + info.page);
		console.log("Pages: " + info.pages);
		console.log("Range: " + info.range);
		return info;

	};
	
	// Focus collection
	bluehat.collection.FocusCollection = Backbone.Collection.extend({
		DEFAULT_LIMIT: 10,
		DEFAULT_SORTBY: 'name_asc',
		
		model: bluehat.model.Focus,
		url: "http://localhost:9000/bluehat/focus/list", 
		
		fetch: function(options) {
			options || (options = {});
			
			if(this.paginated) {
				var iDisplayStart =  encodeURIComponent(this.offset);
				var iDisplayLength = encodeURIComponent(this.limit);	
				var sort_by =  encodeURIComponent(this.sortBy);
				options.data = {iDisplayStart: iDisplayStart, iDisplayLength: iDisplayLength, sort_by: sort_by};		
				console.log(options.data);
			}
			
			return Backbone.Collection.prototype.fetch.call(this, options);
		},
		
		initialize: function(models, options) {
								
			options || (options = {});
			if(options.paginated) this.paginated = true;
			else this.paginated = false;
			
			if(this.paginated) {
				this.offset = options.offset || 0;
				this.limit  = options.limit || this.DEFAULT_LIMIT;
				this.sortBy = options.sortBy || this.DEFAULT_SORTBY; 
			}
		},

		parse: function(resp) {
			console.log("parse");
			if(this.paginated) {
				this.perPage = resp.iDisplayLength;
				this.total = resp.iTotalRecords;
				this.page = resp.start != 0 ? Math.ceil(resp.start / this.perPage) : 1;
				return resp.rows;
			}
			
			return resp;
			
		},					
	});
	
	// Information collection
	bluehat.collection.InformationCollection = Backbone.Collection.extend({
		model: bluehat.model.Information,

		url:  function() {
			return "http://localhost:9000/bluehat/focus/list/" + this.focusId + "/information";
		},

		initialize: function(models, options) {
			
			options || (options = {});
			this.offset = options.offset || 0;
			this.limit  = options.limit || this.DEFAULT_LIMIT;
			this.sortBy = options.sortBy || this.DEFAULT_SORTBY; 

			this.open = true;
			this.remain = true;
			this.closed = true;

			this.focusId = options.focusId;
		},

		fetch: function(options) {
			options || (options = {});
			
			var iDisplayStart =  encodeURIComponent(this.offset);
			var iDisplayLength = encodeURIComponent(this.limit);	
			var sort_by =  encodeURIComponent(this.sortBy);
			var open = encodeURIComponent(this.open ? "true" : "");
			var remain = encodeURIComponent(this.remain ? "true" : "");
			var closed = encodeURIComponent(this.closed ? "true" : "");
			
			options.data = {
						iDisplayStart: iDisplayStart, 
						iDisplayLength: iDisplayLength, 
						sort_by: sort_by,
						open: open,
						remain: remain,
						closed: closed,
			};		
			console.log(options.data);
			
			return Backbone.Collection.prototype.fetch.call(this, options);
		},

		
	});

	bluehat.collection.InfoUnits = Backbone.Collection.extend({
		model: bluehat.model.InfoUnit, 
		url: function() {
			return "/bluehat/information/list/" + this.requestId + "/units";
		},
		
		initialize: function(models, options) {
			options || (options = {})
			this.requestId = options.requestId;
		},
		
		
	});
	// VIEWS
	
	// Focus view: render a li element that will contain the focus information
	bluehat.view.FocusView = Backbone.View.extend({
		tagName: "li",
		template: _.template($("#focus-item-template").html()),
		events: {
			"click button.edit":			"editRow",
			"click button.delete":			"deleteRow",
			"click button.detail":			"detail",
		},

		initialize: function(){
			this.editor = new bluehat.view.FocusEditorView( {model: this.model} );	
			this.confirmation = new bluehat.view.RemoveConfirmationView( {model: this.model} );
			this.model.bind("destroy", this.remove, this);
			
		},
		
		render: function() {
			console.log(this.model.toJSON());
			$(this.el).html(this.template({focus: this.model}));
			$(this.el).append(this.editor.render().el);
			$(this.el).append(this.confirmation.render().el);
			$(this.editor.el).hide();
			$(this.confirmation.el).hide();
			return this;
		},

		editRow: function() {
			console.log("FocusView -> editRow");
			this.editor.show();
			this.confirmation.hide();
		},

		deleteRow: function() {
			this.editor.hide();
			this.confirmation.show();
			console.log("FocusView -> deleteRow");
		},

		detail: function() {
			console.log("FocusView -> detail");
			window.location.hash = "detail" + this.model.get("id"); // TODO use router to go there
		}
	});
	
	// Focus list view: Render a list of focus views
	bluehat.view.FocusListView = Backbone.View.extend({
		tagName: "div",
		id: "focuses",
		template: _.template($("#focus-list-template").html()),
		
		events: {
			"click button.add":		"add",
		},
		
		initialize: function(){
			this.collection.bind("add",  this.refetch, this);
			this.collection.bind("reset", this.render, this);
			this.collection.bind("change", this.render, this);

			this.collection.fetch();
		},

		render: function() {
			$(this.el).html(this.template({}));
			
			
			
			var $list = this.$("ul.focus-list");
			$list.empty();
			var $pagination = this.$("div.pagination");
			$pagination.empty();
			
			this.collection.each(function(focus){
				var item = new bluehat.view.FocusView({collection: this.collection, model: focus});
				$list.append(item.render().el);
			});
			
			var pagination_template =  _.template($("#pagination-template").html());               
			$pagination.append(pagination_template(this.collection.pageInfo()));
				
			return this;
		},

		addAll: function() {
			console.log("addALL");
		},

		refetch: function() {
			console.log("refetch");
		},
		
		add: function() {
			var editor = new bluehat.view.FocusEditorView( {collection: this.collection} );	
			var $newFocus = this.$("#new-focus");
			$newFocus.empty();
			$($newFocus.append(editor.render().el));
			
		},
	});

	// Render a element for confirm or cancel the delete process of one focus.
	bluehat.view.RemoveConfirmationView = Backbone.View.extend({
		template: _.template($("#focus-remove-template").html()),

		events: {
			"click .confirm":		"confirm",
			"click .cancel":		"cancel",
		},

		render: function() {
			$(this.el).html(this.template(this.model.toJSON()));  
			return this;          			
		},

		confirm: function() {
			this.model.destroy();
			$(this.el).remove();
		},

		cancel: function() {
			this.hide();
		},

		show: function() {
			$(this.el).show();
		},

		hide: function() {
			$(this.el).hide();
		},
	});
	
	// Render a focus editor element.
	bluehat.view.FocusEditorView = Backbone.View.extend({
		tagName: "div",
		template: _.template($("#focus-editor-template").html()),
		
		events: {
			"click .close":			"close",
			"click .save":			"save",
			"click .cancel":		"cancel",
		},

		initialize: function(options) {
			_.bindAll(this, "successHandler");
			_.bindAll(this, "errorHandler");
		},
		
		render: function() {
			if(this.model)	$(this.el).html(this.template(this.model.toJSON()));
			else $(this.el).html(this.template({title: "", description: ""}));
			return this;
		},
		
		close: function() {
			console.log("FocusEditor -> closing");
			$(this.el).hide();
		},

		cancel: function() {
			console.log("FocusEditor -> cancel");
			this.close();
		},
		
		show: function() {
			$(this.el).show();
		},

		hide: function() {
			$(this.el).hide();
		},
		
		save: function() {
			console.log("FocusEditor -> save");
			var title = $("#focus_title", this.el).val();
			var description = $("#focus_description", this.el).val();
			if(this.model) {
				console.log("Editando");
				this.model.save( {title: title, description: description}, {success: this.successHandler, error: this.errorHandler} );
			} else {
				console.log("Creando");
				this.collection.create( {title: title, description: description}, {success: this.successHandler, error: this.errorHandler} );
			}
		},

		successHandler: function(model, response) {
			this.close();
		},

		errorHandler: function(model, response) {
			console.log("FocusEditorView -> errorHandler");
			var rJson = jQuery.parseJSON(response.responseText);
			var errors = $("#errors").empty();
			for(var key in rJson.error) {
				if(key.indexOf(".") != -1) {
					var error = "Error: The field " + key + " is " + rJson.error[key];
					errors.append(error);
				} else {
					// TODO
				}	
				
			}
		},
	});
	
	// Renders a list of information views elements
	bluehat.view.InformationListView = Backbone.View.extend({
		tagName: "div",
		className: "informations",
		template: _.template($("#information-list-template").html()),

		events: {
			"click button.open":		"open",
			"click button.remain":		"remain",
			"click button.closed":		"closed",
		},
		
		initialize: function(options) {
			this.model.bind("change", this.render, this);
			this.model.informations.bind("add",  this.refetch, this);
			this.model.informations.bind("reset", this.render, this);
		
			this.model.fetch();
			this.model.informations.fetch();
			//this.collection.fetch();
		},

		open: function() {
			console.log("InformationListView->  open");   
			this.model.informations.open = !this.model.informations.open;
			this.model.informations.refetch();
		},

		remain: function() {
			console.log("InformationListView-> remain");   
			this.model.informations.remain = !this.model.informations.remain;
			this.model.informations.refetch();
		},

		closed: function() {
			console.log("InformationListView-> closed");   
			this.model.informations.closed = !this.model.informations.closed;
			this.model.informations.refetch();
		},
				
		render: function() {
			console.log("InformationListView-> render");   
			console.log(this.model);
			$(this.el).html(this.template({focus: this.model}));
			var that = this;
			this.model.informations.each(function(information){
				console.log(information);
				var infoView = new bluehat.view.InformationView({model: information});
				$(that.el).append(infoView.render().el);
			});
			return this;
		},

		refetch: function() {
			console.log("InformationListView-> refetch");
			this.model.informations.fetch();
		},
	});

	
	// Renders a information view
	bluehat.view.InformationView = Backbone.View.extend({
		tagName: "div",
		className: "information",
		template: _.template($("#information-request-template").html()),

		events: {
			"click button.edit":			"editElement",
			"click button.delete":			"deleteElement",
			"click button.detail":			"detailElement",
			"click .information":			"showUnits",
		},

		initialize: function() {
			this.editor = new bluehat.view.InformationEditorView( {model: this.model} );
		},
		
		showUnits: function() {
			console.log("InformationView-> showUnits");
		},
		
		render: function() {
			console.log("InformationView-> render");
			$(this.el).html(this.template({info: this.model}));
			
			$(this.el).append(this.editor.render().el);
			this.editor.hide();
			
			return this;
		},
		
		editElement: function() {
			console.log("InformationView->  editElement");
			this.editor.show();
		},
		
		deleteElement: function() {
			console.log("InformationView->  deleteElement");
		},
		
		detailElement: function() {
			console.log("InformationView->  detailElement");
			
		},
	});
	
	bluehat.view.InfoUnitListView = Backbone.View.extend({
		tagName: "div",
		className: "info-units-list",
		template: _.template($("#information-unit-list-template").html()),
		
		initialize: function(options) {
		
			this.collection.bind("reset", this.render, this);
			this.collection.bind("change", this.render, this);
			
			this.collection.fetch();
		},
		
		render: function() {
			console.log("InfoUnitListView  -> render");
			
			var infoRequest = this.collection.length > 0 ? this.collection.at(0).inforequest : {};
			console.log("------------");
			console.log(infoRequest);
			$(this.el).html(this.template({infoRequest: infoRequest }));
			
			var $list = $("#info-unit-list", this.el);
			$list.empty();
			this.collection.each(function(unit){
				console.log("Iterando");
				console.log(unit.toJSON());
				var infoUnitView = new bluehat.view.InfoUnitView( {model: unit} );
				$list.append(infoUnitView.render().el);
			});
			
			return this;
		},	
	});
	
	bluehat.view.InfoUnitView = Backbone.View.extend({
		initialize: function() {
			this.template = _.template($("#information-unit-detail-template").html());
		},
		
		render: function() {
			console.log(this.model.toJSON());
			$(this.el).html(this.template(this.model.toJSON()));
			return this;
		},
	});
	
	bluehat.view.ErrorsView = Backbone.View.extend({
		el: "#errors",
		
		spans: [],
		
		initialize: function(options) {
			this.error = {};
		},
		
		clean: function() {
			$(this.el).empty();
			
			for(key in this.spans) {
				var span = this.spans[key];
				span.remove();
			}
			
		},
		
		render: function() {
			this.clean();
			for(var key in this.error) {
				var inputKey = key.replace(".", "_");
				var input = $("#"+inputKey);
				if(input.length > 0) {
					var span = $("<span></span>", {html: this.error[key]});
					input.after(span);
					this.spans[key] = span;
				} else {
					var p = $("<p></p>", {html: this.error[key]}).addClass("error");
					$(this.el).append(p);
				}
			}
			
			return this;
		},
	});
	
	// Render a focus editor element.
	bluehat.view.InformationEditorView = Backbone.View.extend({
		tagName: "div",
		template: _.template($("#information-editor-template").html()),
		
		events: {
			"click button.close":			"close",
			"click button.save":			"save",
			"click button.cancel":			"cancel",
		},

		initialize: function(options) {
			_.bindAll(this, "successHandler");
			_.bindAll(this, "errorHandler");
		},
		
		render: function() {
			console.log("InformationEditorView -> render");
			console.log(this.model.toJSON());
			if(this.model)	$(this.el).html(this.template(this.model.toJSON()));
			else $(this.el).html(this.template({title: "", description: ""}));
			
			$("#information_start", this.el).datetimepicker({dateFormat: 'yyyy/mm/dd HH:MM:ss'});
			$("#information_end", this.el).datetimepicker({dateFormat: 'yyyy/mm/dd HH:MM:ss'});
			
			return this;
		},
		
		close: function() {
			console.log("InformationEditorView-> closing");
			$(this.el).hide();
		},

		cancel: function() {
			console.log("InformationEditorView -> cancel");
			this.close();
		},
		
		show: function() {
			$(this.el).show();
		},

		hide: function() {
			$(this.el).hide();
		},
		
		save: function() {
			console.log("InformationEditorView -> save");
			var description = $("#information_description", this.el).val();
			var start = $("#information_start", this.el).datetimepicker( "getDate" ).getTime();
			var end = $("#information_end", this.el).datetimepicker( "getDate" ).getTime();
			
			if(this.model) {
				console.log("Editando");
				this.model.save( {description: description, start: start, end: end}, {success: this.successHandler, error: this.errorHandler} );
			} else {
				console.log("Creando");
				this.collection.create( {description: description, start: start, end: end}, {success: this.successHandler, error: this.errorHandler} );
			}
		},

		successHandler: function(model, response) {
			this.close();
		},

		errorHandler: function(model, response) {
			console.log("FocusEditorView -> errorHandler");
			var rJson = jQuery.parseJSON(response.responseText);
			var errors = $("#errors").empty();
			for(var key in rJson.error) {
				if(key.indexOf(".") != -1) {
					var error = "Error: The field " + key + " is " + rJson.error[key];
					errors.append(error);
				} else {
					// TODO
				}	
				
			}
		},
	});
	
	// User summary view
	bluehat.view.UserSummaryView = Backbone.View.extend({
		tagName: "div",
		className: "user-summary",
		
		initialize: function(options) {
			this.template = _.template($("#user-profile-template").html());
			this.model.bind("change", this.render, this);
			this.model.units.bind("reset", this.renderActivity, this);
			this.model.fetch();
			this.model.units.fetch();
		},
		
		render: function() {
			console.log(this.model.toJSON());
			$(this.el).html(this.template(this.model.toJSON()));
			
			return this;
		},
		
		renderActivity: function() {
			console.log("UserSummaryView -> renderActivity");
			var $activity = this.$(".activity");
			$activity.empty();
			this.model.units.each(function(unit){
				var unitView = new bluehat.view.InfoUnitView({model: unit});
				$activity.append(unitView.render().el);
			});
		}
	});
	
	// App view
	bluehat.view.AppView = Backbone.View.extend({
		el: "#content",

		initialize: function() {
			
		},
	});

	// ROUTER
	bluehat.router.AppRouter = Backbone.Router.extend({
		routes: {
			"": 						"start",
			"page:p": 					"changePage",
			"listinformations:id":		"listinformations",
			"infounits:id":				"infounits",
			"user:id":					"usersumary",
		},

		initialize: function( options ) {
			this.focusCollection = options.focusCollection;
			this.appView = new bluehat.view.AppView();
			
		},
		
		start: function() {
			var focusListView = new bluehat.view.FocusListView({collection: this.focusCollection} );
			$(this.appView.el).html(focusListView.render().el);
		},
		
		changePage: function( page ) {
			var start = (page-1) * this.focusCollection.limit;
			this.focusCollection.offset = start;
			this.focusCollection.fetch();
			var focusListView = new bluehat.view.FocusListView( {collection: this.focusCollection} );
			$(this.appView.el).html(focusListView.render().el);
		},

		listinformations: function( id ) {
			console.log("AppRouter -> listinformations focus id: " + id);
			var focus = new bluehat.model.Focus({id : id});
			
			var informationListView = new bluehat.view.InformationListView( {model: focus} );
			$(this.appView.el).html(informationListView.render().el);
		},
		
		infounits: function( id ) {
			console.log("AppRouter -> infounits info request id: " + id);
			
			var units = new bluehat.collection.InfoUnits([], {requestId: id});
			var infoUnitListView = new bluehat.view.InfoUnitListView({collection: units} );
			$(this.appView.el).html(infoUnitListView.render().el);
		},
		
		usersumary: function( id ) {
			console.log("AppRouter -> usersumary user id: " + id);
			var user = new bluehat.model.User({id: id});
			var userSummaryView = new bluehat.view.UserSummaryView({model: user});
			$(this.appView.el).html(userSummaryView.render().el);
		}
		
	});
	
	return bluehat;
};